package com.wquick.base.utils.asyncTask

import java.util.concurrent.*
import java.util.concurrent.atomic.AtomicInteger

object AsyncTaskExecutors {

    /* 不定长 */
    val UNBOUNDED by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
        Executors.newCachedThreadPool(NumberThreadFactory("bat-async-unbounded"))
    }

    /* 定长 */
    val BOUNDED by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
        Executors.newFixedThreadPool(requireThreads(), NumberThreadFactory("bat-async-bounded"))
    }

    /* 有序 */
    val SERIAL by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
        Executors.newSingleThreadExecutor(NumberThreadFactory("bat-async-serial"))
    }

    fun newCachedSingleThreadExecutor(name: String): ExecutorService {
        val executor = ThreadPoolExecutor(1, 1, 15, TimeUnit.SECONDS, LinkedBlockingQueue()) { r -> Thread(r, name) }
        executor.allowCoreThreadTimeOut(true)
        return executor
    }

    fun newFixedThreadExecutor(name: String): ExecutorService {
        return Executors.newFixedThreadPool(requireThreads(), NumberThreadFactory(name))
    }

    fun newCachedThreadPool(name: String): ExecutorService {
        return Executors.newCachedThreadPool(NumberThreadFactory(name))
    }

    private fun requireThreads(): Int {
        return 2.coerceAtLeast((Runtime.getRuntime().availableProcessors() - 1).coerceAtMost(4))
    }

    private class NumberThreadFactory constructor(private val baseName: String) : ThreadFactory {

        private val counter by lazy { AtomicInteger() }

        override fun newThread(r: Runnable): Thread {
            return Thread(r, baseName + "-" + counter.getAndIncrement())
        }
    }
}
